home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / asm / adisv1_3.lha / src / analyze.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-21  |  11.2 KB  |  446 lines

  1. /*
  2.  * Change history
  3.  * $Log:    analyze.c,v $
  4.  * Revision 3.0  93/09/24  17:53:48  Martin_Apel
  5.  * New feature: Added extra 68040 FPU opcodes
  6.  * 
  7.  * Revision 2.5  93/07/18  22:55:38  Martin_Apel
  8.  * *** empty log message ***
  9.  * 
  10.  * Revision 2.4  93/07/13  11:40:29  Martin_Apel
  11.  * Bug fix: Premature abortion aof analysis is now handled correctly
  12.  *          (see log for amiga.c)
  13.  * 
  14.  * Revision 2.3  93/07/11  21:37:30  Martin_Apel
  15.  * Major mod.: Jump table support tested and changed
  16.  * 
  17.  * Revision 2.2  93/07/10  13:01:34  Martin_Apel
  18.  * Major mod.: Added full jump table support. Seems to work quite well
  19.  * 
  20.  * Revision 2.1  93/07/08  20:46:25  Martin_Apel
  21.  * Minor mod.: Moved jump table recognition to examine_unknown_labels
  22.  * 
  23.  * Revision 2.0  93/07/01  11:53:42  Martin_Apel
  24.  * *** empty log message ***
  25.  * 
  26.  * Revision 1.21  93/07/01  11:37:31  Martin_Apel
  27.  * Minor mod.: Removed dependance on ctype.h
  28.  * 
  29.  * Revision 1.20  93/06/16  20:25:36  Martin_Apel
  30.  * Minor mod.: Moved jump table code to jumptab.c
  31.  * 
  32.  * Revision 1.19  93/06/06  13:44:55  Martin_Apel
  33.  * Minor mod.: Added preliminary support for jump tables recognition
  34.  * 
  35.  * Revision 1.18  93/06/06  00:09:59  Martin_Apel
  36.  * Bug fix: Small change regarding recognition of jump tables
  37.  * 
  38.  * Revision 1.18  93/06/06  00:08:12  Martin_Apel
  39.  * Minor mod.: Fixed bug regarding jump tables
  40.  * 
  41.  * Revision 1.17  93/06/03  20:25:06  Martin_Apel
  42.  * 
  43.  */
  44.  
  45. #include <exec/types.h>
  46. #include <stdio.h>
  47. #include <string.h>
  48. #include <assert.h>
  49. #include "defs.h"
  50.  
  51. #ifdef AZTEC_C
  52. void Chk_Abort (void);
  53. #endif
  54.  
  55. static char rcsid [] = "$Id: analyze.c,v 3.0 93/09/24 17:53:48 Martin_Apel Exp $";
  56.  
  57. PRIVATE BOOL first_try = TRUE;
  58.  
  59. /**********************************************************************/
  60.  
  61. void save_flags (void)
  62.  
  63. {
  64. register ULONG *ptr,
  65.                *seg_end;
  66.  
  67. make_labels_permanent ();
  68. seg_end = (ULONG*)(flags + (last_address - first_address));
  69. ptr = (ULONG*)flags;
  70. while (ptr < seg_end)
  71.   {
  72.   SAVE_LONG (*ptr);
  73.   ptr++;
  74.   }
  75. }
  76.  
  77. /**********************************************************************/
  78.  
  79. void restore_flags (void)
  80.  
  81. {
  82. register UBYTE *ptr,
  83.                *seg_end;
  84.  
  85. delete_tmp_labels ();
  86. ptr = flags;
  87. seg_end = flags + last_address - first_address;
  88. while (ptr < seg_end)
  89.   {
  90.   if (*ptr & NEW)
  91.     RESTORE (*ptr);
  92.   ptr++;
  93.   }
  94. }
  95.  
  96. /*************************************************************************/
  97.  
  98. PRIVATE void get_first_code_label (void)
  99.  
  100. {
  101. char *dummy;
  102. UWORD access;
  103.  
  104. /* get first code label in this hunk */
  105. current_address = first_address;
  106. if (!(find_active_reference (first_address, &dummy, &access) && 
  107.       (access & ACC_CODE)))
  108.   {
  109.   do
  110.     current_address = next_active_reference (current_address, 
  111.                                              last_address, &access);
  112.   while (current_address < last_address && !(access & ACC_CODE));
  113.   }
  114. }
  115.  
  116. /**********************************************************************/
  117.  
  118. PRIVATE void examine_direct_refs (USHORT *seg, ULONG seg_size)
  119.  
  120. /**********************************************************************/
  121. /*  This routine starts disassembling from current_address and then   */
  122. /*                 continuing where code labels are.                  */
  123. /**********************************************************************/
  124. {
  125. register short instr_size;
  126. UWORD access;
  127. BOOL examined_direct_refs = FALSE;
  128. register int i;
  129. ULONG stream_start;
  130. char *dummy;
  131.  
  132. while (!examined_direct_refs)
  133.   {
  134.   do
  135.     {
  136.     if (!IS_SURE (current_address))
  137.       {
  138.       code = seg + (current_address - first_address) / 2;
  139.       end_instr = FALSE;
  140.       examined_direct_refs = FALSE;
  141.       if (verbose)
  142.         {
  143.         printf (">%5lx\r", current_address);
  144.         fflush (stdout);
  145.         }
  146. #ifdef AZTEC_C
  147.       else
  148.         Chk_Abort ();
  149. #endif
  150.       stream_start = current_address;
  151.       do
  152.         {
  153.         instr_size = disasm_instr ();
  154.         if (detected_illegal || (current_address + 2 * instr_size > 
  155.              next_reference (current_address, last_address, &access)) ||
  156.              IS_RELOCATED (current_address))
  157.           {
  158.           restore_flags ();
  159.           if (print_illegal_instr_address)
  160.             {
  161.             printf ("Illegal instruction found at address: %lx\n", 
  162.                      current_address);
  163.             }
  164.           first_try = FALSE;
  165.           detected_illegal = FALSE;
  166.           return;
  167.           }
  168.  
  169.         for (i = 0; i < instr_size; i++)
  170.           {
  171.           assert (current_address - first_address + i * 2 + 1 < seg_size);
  172.           *((UWORD*)(flags + current_address - first_address + i * 2)) |=
  173.                     ((TMP_CODE | NEW) << 8) | (TMP_CODE | NEW);
  174.           }
  175.         code += instr_size;
  176.         current_address += instr_size * 2;
  177.         }
  178.       while (!end_instr && current_address < last_address &&
  179.                            !IS_SURE (current_address));
  180.  
  181.       deactivate_labels (stream_start, current_address);      
  182.       }
  183.     else
  184.       deactivate_labels (current_address, current_address + 2);      
  185.       
  186.     /* advance current_address until next address which has not been 
  187.        examined yet. Then find the next label from there on */
  188.     if (!(find_active_reference (current_address, &dummy, &access) &&
  189.           access & ACC_CODE))
  190.       {
  191.       access = 0;
  192.       while (!(access & ACC_CODE) && current_address < last_address)
  193.         current_address = next_active_reference (current_address, 
  194.                                                  last_address, &access);
  195.       }
  196.     }
  197.   while (current_address < last_address);
  198.   get_first_code_label ();
  199.   if (current_address == last_address)
  200.     examined_direct_refs = TRUE;  
  201.   }
  202. }
  203.  
  204. /************************************************************************/
  205.  
  206. PRIVATE BOOL examine_unknown_labels (UWORD *seg, ULONG seg_size)
  207.  
  208. {
  209. BOOL new_labels_found;
  210. char *maybe_string;
  211. int length;
  212. UWORD access;
  213. int i;
  214.  
  215. new_labels_found = FALSE;
  216. current_address = first_address;
  217.  
  218. while (current_address < last_address)
  219.   {
  220.   if (!IS_PROBABLE (current_address))
  221.     {
  222.     if (verbose)
  223.       {
  224.       printf (">%5lx\r", current_address);
  225.       fflush (stdout);
  226.       }
  227. #ifdef AZTEC_C
  228.       else
  229.         Chk_Abort ();
  230. #endif
  231.     maybe_string = (char*)seg + (current_address - first_address);
  232.  
  233.     if ((ODD (current_address)) || 
  234.         (is_string (maybe_string, last_address - current_address) && 
  235.          *(USHORT*)maybe_string != 0x4e55))
  236.       {
  237.       /* label is at an odd address, or it's definitely a string but not
  238.          a link instruction */
  239.       length = strlen (maybe_string) + 1;
  240.       if (current_address + length > last_address)
  241.         {
  242.         *(flags + (current_address - first_address)) |= 
  243.                                                   TMP_DATA | NEW;
  244.         assert (current_address - first_address < seg_size);
  245.         }
  246.       else if (first_try && length < 5 &&
  247.                next_reference (current_address, last_address, &access) -
  248.                current_address > 10 && !ODD (current_address))
  249.         {
  250.         new_labels_found = TRUE;
  251.         break;
  252.         }
  253.       else
  254.         {
  255.         for (i = 0; i < length; i++)
  256.           {
  257.           *(flags + (current_address - first_address + i)) |= 
  258.                                     TMP_STRING | NEW;
  259.           assert (current_address - first_address + i < seg_size);
  260.           }
  261.         deactivate_labels (first_address, current_address + 1);
  262.         save_flags ();
  263.         first_try = TRUE;
  264.         }
  265.       }
  266.     else if (first_try)
  267.       {
  268.       /* try to disassemble it */
  269.       new_labels_found = TRUE;
  270.       break;
  271.       }
  272.     else 
  273.       {
  274.       *(flags + (current_address - first_address)) |= TMP_DATA;
  275.       *(flags + (current_address - first_address) + 1) |= TMP_DATA;
  276.       first_try = TRUE;
  277.       deactivate_labels (first_address, current_address);
  278.       save_flags ();
  279.       }
  280.     }
  281.  
  282.   current_address = next_active_reference (current_address, 
  283.                                            last_address, &access);
  284.   }
  285.  
  286. deactivate_labels (first_address, current_address);
  287. return (new_labels_found);
  288. }
  289.     
  290. /**************************************************************************/
  291.  
  292. PRIVATE BOOL guess (UWORD *seg, ULONG seg_size)
  293.  
  294. {
  295. /*
  296.  * Try to disassemble the rest of the code segment.  There are no
  297.  * labels left where to orient.  
  298.  */
  299.  
  300. UBYTE *ptr,
  301.       *seg_end;
  302. static ULONG last_guessed_address;
  303.  
  304.  
  305. if (!first_try)
  306.   {
  307.   if (invalidate_last_jmptab_entry ())
  308.     first_try = TRUE;
  309.   }
  310.  
  311. if (next_code_ref_from_jmptab (seg))
  312.   {
  313.   current_address = first_address;
  314.   return (TRUE);
  315.   }
  316.  
  317. ptr = flags;
  318. code = seg;
  319. seg_end = flags + last_address - first_address;
  320.  
  321. if (!first_try)
  322.   {
  323.   *(flags + last_guessed_address - first_address) |= PERM_DATA | TMP_DATA;
  324.   *(flags + last_guessed_address - first_address + 1) |= PERM_DATA | TMP_DATA;
  325.   first_try = TRUE;
  326.   }
  327.  
  328. while (ptr < seg_end && (IS_PROBABLE_P (ptr) ||
  329.        ((*code != 0x48e7) &&                                /* MOVEM ,-(SP) */
  330.         (*code != 0x4e55) &&                                /* LINK instr. */
  331.         (*code != 0x6000) &&                                /* BRA.L */
  332.         (*code != 0x6100) &&                                /* BSR.L */
  333.         (*code != 0x4efa) &&                                /* JMP d16(PC) */
  334.         !((*code == 0x4ef9) && IS_RELOCATED_P (ptr + 2)) && /* JMP xxx.L */
  335.         (*code != 0x4eba) &&                                /* JSR d16(PC) */
  336.         !((*code == 0x4eb9) && IS_RELOCATED_P (ptr + 2))))) /* JSR xxx.L */
  337.   {
  338.   ptr += 2;
  339.   code++;
  340.   }
  341.  
  342. if (ptr >= seg_end)
  343.   return (FALSE);
  344.  
  345. last_guessed_address = first_address + ptr - flags;
  346. current_address = last_guessed_address;
  347. return (TRUE);
  348. }
  349.  
  350. /***************************************************************************/
  351.  
  352. PRIVATE void last_touch (UWORD *seg, ULONG seg_size)
  353.  
  354. {
  355. for (current_address = first_address; current_address < last_address; 
  356.      current_address++)
  357.   {
  358.   if (!IS_PROBABLE (current_address))
  359.     *(flags + (current_address - first_address)) |= TMP_DATA;
  360.   assert (current_address - first_address < seg_size);
  361.   }
  362. }
  363.  
  364. /***************************************************************************/
  365.  
  366.  
  367.  
  368. void disasm_code_1st (USHORT *seg, ULONG seg_size)
  369.  
  370. {
  371. BOOL examine_direct;
  372. BOOL new_labels;
  373. BOOL aborted = FALSE;
  374.  
  375. get_first_code_label ();
  376. if (current_address < last_address)
  377.   examine_direct = TRUE;
  378. else
  379.   examine_direct = FALSE;
  380.  
  381. first_try = TRUE;
  382. do
  383.   {
  384.   do
  385.     {
  386.     if (examine_direct)
  387.       {
  388.       examine_direct_refs (seg, seg_size);
  389.       save_flags ();
  390.       }
  391.     examine_direct = TRUE;
  392.     new_labels = examine_unknown_labels (seg, seg_size);
  393.     aborted = user_aborted_analysis ();
  394.     } 
  395.   while (new_labels && !aborted);
  396.  
  397.   new_labels = guess (seg, seg_size);
  398.   aborted = aborted || user_aborted_analysis ();
  399.   } 
  400. while (new_labels && !aborted);
  401. last_touch (seg, seg_size);
  402. }
  403.  
  404. /***************************************************************************/
  405.  
  406. #ifdef DEBUG
  407.  
  408. void print_flags (ULONG from)
  409.  
  410. {
  411. ULONG count;
  412. char id;
  413.  
  414. for (count = 0; count < 0x40; count++)
  415.   {
  416.   if ((count % 0x10) == 0)
  417.     printf ("%lx: ", from + count);
  418.  
  419.   if (IS_CODE (from + count))
  420.     if (IS_SURE (from + count))
  421.       id = 'C';
  422.     else
  423.       id = 'c';
  424.   else if (IS_DATA (from + count))
  425.     if (IS_SURE (from + count))
  426.       id = 'D';
  427.     else
  428.       id = 'd';
  429.   else if (IS_STRING (from + count))
  430.     if (IS_SURE (from + count))
  431.       id = 'S';
  432.     else
  433.       id = 's';
  434.   else
  435.     id = '?';
  436.  
  437.   printf ("%c ", id);
  438.   if ((count % 0x10) == 0xf)
  439.     printf ("\n");
  440.   }
  441.  
  442. printf ("\n");
  443. }
  444.  
  445. #endif
  446.